package com.ksyun.alert.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ksyun.alert.biz.bo.timing.TimingExpressionResolveBO;
import com.ksyun.alert.entity.MonitorDatasDO;
import com.ksyun.alert.mapper.MonitorDatasMapper;
import com.ksyun.alert.service.MonitorDatasService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 日常监控数据表接口实现层
 *
 * @author: hantou
 * @date: 2024-05-05
 */
@Service
public class MonitorDatasServiceImpl extends ServiceImpl<MonitorDatasMapper, MonitorDatasDO> implements MonitorDatasService {
    @Override
    public List<List<MonitorDatasDO>> getSpecifiedTimePeriodMonitorData(List<String> metricNameList, Long startTimestamp, Long endTimestamp) {
        LambdaQueryWrapper<MonitorDatasDO> queryWrapper = Wrappers.lambdaQuery(MonitorDatasDO.class)
                .in(MonitorDatasDO::getMetricName, metricNameList)
                .ge(MonitorDatasDO::getTimestamp, startTimestamp)
                .le(MonitorDatasDO::getTimestamp, endTimestamp);
        List<MonitorDatasDO> monitorDataList = this.getBaseMapper().selectList(queryWrapper);
        return trans2ListBatchByTimestamp(monitorDataList);
    }

    @Override
    public List<MonitorDatasDO> getSpecifiedTimeNewestMonitorData(List<String> metricList, Long endTimestamp) {
        List<MonitorDatasDO> monitorDataList = new ArrayList<>();
        for (String metric : metricList) {
            LambdaQueryWrapper<MonitorDatasDO> queryWrapper = Wrappers.lambdaQuery(MonitorDatasDO.class)
                    .eq(MonitorDatasDO::getMetricName, metric)
                    .le(MonitorDatasDO::getTimestamp, endTimestamp)
                    .ge(MonitorDatasDO::getTimestamp, endTimestamp - 30) // 超出30s的就不查了
                    .orderByDesc(MonitorDatasDO::getTimestamp)
                    .last("LIMIT 1");
            MonitorDatasDO monitorData = this.getBaseMapper().selectOne(queryWrapper);
            if (monitorData != null) {
                monitorDataList.add(monitorData);
            }
        }
        return monitorDataList;
    }

    @Override
    public List<List<MonitorDatasDO>> getSpecifiedTimePeriodMonitorData(TimingExpressionResolveBO timingExpressionResolveBO, long nowTimestamp) {
        Map<String, Long> metricPeriodMap = timingExpressionResolveBO.getMetricPeriodMap();

        List<MonitorDatasDO> monitorDataList = new ArrayList<>();
        metricPeriodMap.forEach((k, v) -> {
            LambdaQueryWrapper<MonitorDatasDO> queryWrapper = Wrappers.lambdaQuery(MonitorDatasDO.class)
                    .eq(MonitorDatasDO::getMetricName, k)
                    .ge(MonitorDatasDO::getTimestamp, nowTimestamp - v)
                    .le(MonitorDatasDO::getTimestamp, nowTimestamp);
            monitorDataList.addAll(this.getBaseMapper().selectList(queryWrapper));
        });

        return trans2ListBatchByTimestamp(monitorDataList);
    }

    /**
     * 根据时间戳分组数据
     */
    private List<List<MonitorDatasDO>> trans2ListBatchByTimestamp(List<MonitorDatasDO> monitorDataList) {
        return new ArrayList<>(monitorDataList.stream()
                .collect(Collectors.groupingBy(MonitorDatasDO::getTimestamp))
                .values());
    }
}
